// STRING/TIME FORMATTING

function makeStr(n)
{
    if(n < 10)
        return '0' + n;
    else
        return '' + n;
}

function myParseInt(s)
{
    var n = parseInt(s);
    if(!/^\d+$/.test(s))
        return NaN;
    if(isNaN(n) || n < 0)
        return NaN;
    return n;
}

function parseSpent(s)
{
    s = s.replace(/\s+/, "");
    if(s == '')
        return 0;
    var h = 0;
    var m = 0;
    var i = s.indexOf(':');
    if(i != -1)
    {
        h = myParseInt(s.substring(0, i));
        if(isNaN(h))
            return null;
        if(s.length > i + 1)
        {
            m = myParseInt(s.substring(i + 1, s.length));
            if(isNaN(m) || m > 59)
                return null;
        }
    }
    else
    {
        h = myParseInt(s);
        if(isNaN(h))
            return null;
    }
    return h * 60 + m;
}

function formatSpent(n)
{
    return Math.round(n / 60 - n % 60 / 60) + ":" + makeStr(n % 60);
}

// OVERTIME FUNCTIONS
// returns overtime for a given day from input
function getOvertimeForDay(f, day)
{
    if(f.elements["overtime[" + day + "]"])
        return parseSpent(f.elements["overtime[" + day + "]"].value);
}

// returns workday duration for a given day
function getWorkdayDuration(f, day)
{
    if(f.elements["dayType[" + day + "]"])
        return f.elements["dayType[" + day + "]"].value;
}

// gets auto overtime for a given day
function getAutoOvertimeForDay(f, day)
{
    dayTotal = getDayTotal(f, day);
    overtime = getOvertimeForDay(f, day);
    workdayDuration = getWorkdayDuration(f, day);
    return (dayTotal - workdayDuration > 0) ? dayTotal - workdayDuration : 0;
}

// calculates autoovertime for a single day, sets values for this day and total overtime, hides exclamation
function calcOvertime(day)
{
        dayTotal = getDayTotal(document.SubmitTTForm, day);
        workdayDuration = getWorkdayDuration(document.SubmitTTForm, day);

        if(document.SubmitTTForm.elements["overtime[" + day + "]"])   {
            newValue = (dayTotal - workdayDuration > 0) ? formatSpent(dayTotal - workdayDuration) : formatSpent(0);
            document.SubmitTTForm.elements["overtime[" + day + "]"].value = newValue;
        }
        setOvertimeExclamation(day, false);
        recalculateTotalOvertime(document.SubmitTTForm);
}

// sets overtime exclamation for a given day
function setOvertimeExclamation(day, state)
{
    if(document.images["overtimeImg[" + day + "]"])
    {
        if(state) {
            document.images["overtimeImg[" + day + "]"].src = "../img/exclamation.gif";
            document.images["overtimeImg[" + day + "]"].alt = "Overtime differs from the automatically calculated value";
            document.images["overtimeImg[" + day + "]"].title = "Overtime differs from the automatically calculated value";
        }
        else   {
            document.images["overtimeImg[" + day + "]"].src = "../img/pixel.gif";
            document.images["overtimeImg[" + day + "]"].alt = "";
            document.images["overtimeImg[" + day + "]"].title = "";
        }
    }
}

// recalculates total overtime and sets value to the input
function recalculateTotalOvertime(f)
{
    if(f.overtimeTotal) {
      var total = 0;
      for(day = 0; day < 7; day++)
      {
        if(f.elements["overtime[" + day + "]"])
            total += parseSpent(f.elements["overtime[" + day + "]"].value);
      }
      f.overtimeTotal.value = formatSpent(total);
    }
}

// handler for onchange on the overtime inputs. validates input, sets exclamation, sets/removes data_modified flag
// invokes recalculation of total overtime
function checkOvertime(element, day)
{
    dayTotal = getDayTotal(element.form, day);
    overtime = parseSpent(element.value);
    workdayDuration = getWorkdayDuration(element.form, day);
    if(overtime == null)  {
         if(!dataModified[element.name])
            dataModified[element.name] = element;
        return true;
    }

    autoOvertime = (dayTotal - workdayDuration > 0) ? dayTotal - workdayDuration : 0;

    if(autoOvertime != overtime)
        setOvertimeExclamation(day, true);
    else
        setOvertimeExclamation(day, false);

    if(overtime != parseSpent(element.defaultValue)) {
         if(!dataModified[element.name])
            dataModified[element.name] = element;
    } else {
         if(dataModified[element.name])
            delete dataModified[element.name];
    }
    recalculateTotalOvertime(element.form);
    return true;
}

// handles body.onload
// shows/hides overtime exclamation marks, fills empty overtime inputs with starting values
// ("" or "0:00" depending on exclamation status)
function showExclamationMarks()
{
  for(i =0; i<7; i++)
  {
      var autoOvertime = getAutoOvertimeForDay(document.forms.SubmitTTForm, i);
      var overtime =  getOvertimeForDay(document.forms.SubmitTTForm, i);
      var timeTrack = getDayTotal(document.forms.SubmitTTForm, i);
      if(overtime != autoOvertime)
      {
        setOvertimeExclamation(i, true);
      }
      if(overtime == 0) {
          if(timeTrack != 0) {
              if(document.forms.SubmitTTForm.elements["overtime[" + i + "]"]) {
                  document.forms.SubmitTTForm.elements["overtime[" + i + "]"].value = formatSpent(0);
              }
          }
          else
              if(document.forms.SubmitTTForm.elements["overtime[" + i + "]"]) {
                  document.forms.SubmitTTForm.elements["overtime[" + i + "]"].value = "";
              }
      }
  }
}


// TIME_TRACK FUNCTIONS
// returns day total for a given day. takes it from input.
function getDayTotal(f, day)
{
   var e = f.elements["dayTotal[" + day + "]"];
   if(e)
      return parseSpent(e.value);
   else
      return 0;
}

// handles onchange event on time-track inputs.
// validates the input, updates day total, updates week total, sets/removes data modified flag,
// sets/removes overtime exclamation
function checkSpent(day, field, e)
{
    var invalidEntry = false;
    nowValue = parseSpent(field.value);
    if(nowValue == null) {
        nowValue = 0;
        invalidEntry = true;
        if(!dataModified[field.name])
           dataModified[field.name] = field;
        if(currentValue == null) return true;
    }

        // check if data was updated
        if(nowValue == currentValue) return true;

        // get daytotal
        f = field.form;
        if(f.elements["dayTotal[" + day + "]"])
        {
             dayTotal = parseSpent(f.elements["dayTotal[" + day + "]"].value);
             // update dayTotal
             dayTotal += nowValue - currentValue;
        }
        if(f.elements["dayTotal[" + day + "]"])
        {
             f.elements["dayTotal[" + day + "]"].value = formatSpent(dayTotal);
             // quick weekTotal recalculation
             if(f.weekTotal)
                f.weekTotal.value = formatSpent(parseSpent(f.weekTotal.value) + nowValue - currentValue);
        }
        if(!invalidEntry) {
            if(nowValue != parseSpent(field.defaultValue)) {
                 if(!dataModified[field.name])
                    dataModified[field.name] = field;
            } else {
                 if(dataModified[field.name])
                    delete dataModified[field.name];
            }
        }
        // update overtime sign
        autoOvertime = getAutoOvertimeForDay(f, day);
        overtime = getOvertimeForDay(f, day);
        if(autoOvertime != overtime)
            setOvertimeExclamation(day, true);
        else
            setOvertimeExclamation(day, false);
        return true;
}

// handler for onfocus event on time-track input fields. saves the value to the global variable
function focusSpent(day, field)
{
    currentValue = parseSpent(field.value);
    return true;
}

// calculates total for a given task
function calculateTimeTrack(taskId)
{
   var total = 0;
   for(i = 0; i < 7; i++)
   {
        if(document.SubmitTTForm.elements["timeTrack[" + taskId + "].spentStr[" + i + "]"])
            total += parseSpent(document.SubmitTTForm.elements["timeTrack[" + taskId + "].spentStr[" + i + "]"].value);
   }
   return total;
}

// invokes deletion of a time-track
function deleteTimeTrack(taskId)
{
    var b;
    if(calculateTimeTrack(taskId) == 0 && !commentsPresent(taskId))
        b = true;
    else
        b = confirm('Are you sure you want to delete the row? Spent time and/or comments entered for this week will be lost.');
    if(b)
    {
        document.SubmitTTForm.deleteTimeTrack.value = '' + taskId;
        // here we check if timeTrack to be deleted is the only modified data
        for(i = 0; i < 7; i++)
        {
            s1 = "timeTrack[" + taskId + "].spentStr[" + i + "]";
            if(dataModified[s1])
                delete dataModified[s1];
            s1 = "timeTrack[" + taskId + "].comment[" + i + "]";
            if(dataModified[s1])
                delete dataModified[s1];
        }
        modifiedCount = 0;
        for(var k in dataModified)
            modifiedCount++;
        if(modifiedCount != 0) {
            document.SubmitTTForm.dataModified.value = 1;
        }

        document.SubmitTTForm.submit();
    }
}

// checks if data had been modified
function isModified()
{
    if(document.SubmitTTForm.dataModified.value == 1) return true;
    for(var i in dataModified)
    {
        if(dataModified[i])
            return true;
    }
    return false;
}

function calculateSum(f, nameStr)
{
    var total = 0;
    for(i = 0; i < f.elements.length; i++)
    {
        if(f.elements[i].name.indexOf(nameStr) != -1)
        {
            n = parseSpent(f.elements[i].value);
            if(n)
                total += n;
        }
    }
    return formatSpent(total);
}

function recalculateDay_noWeekTotalUpdate(f, day)
{
    var dayTotal = calculateSum(f, ".spentStr[" + day + "]");
    if(f.elements["dayTotal[" + day + "]"])
    {
        f.elements["dayTotal[" + day + "]"].value = dayTotal;
    }
    return dayTotal;
}

function recalculateDay(f, day)
{
    var dayTotal = recalculateDay_noWeekTotalUpdate(f, day);
    if(f.weekTotal)
    {
        f.weekTotal.value = calculateSum(f, "dayTotal");
    }
    return dayTotal;
}

function recalculateWeek(f)
{
    recalculateDay_noWeekTotalUpdate(f, 0);
    recalculateDay_noWeekTotalUpdate(f, 1);
    recalculateDay_noWeekTotalUpdate(f, 2);
    recalculateDay_noWeekTotalUpdate(f, 3);
    recalculateDay_noWeekTotalUpdate(f, 4);
    recalculateDay_noWeekTotalUpdate(f, 5);
    recalculateDay(f, 6);
}

function SubmitTimeTrack(evt)
{
    var event = evt ? evt : (window.event ? window.event : null);
    for(var i in dataModified)
    {
        var name = dataModified[i].name;
        // timetrack?
        if(name.indexOf('spentStr[') != -1) {
            var spent = parseSpent(dataModified[i].value);
            var day = name.substr(name.length - 2, 1);
            var total = getDayTotal(document.SubmitTTForm, day);
            if(spent == null) {
                var message = "Time-track submitted for " + calLayout[day] + ' contains incorrect value: "' + dataModified[i].value + "\".\n" +
                              "Time should be entered in the format hh:mm. Number of minutes must be less than 60.\n\n" +
                              "Please correct the time value before submitting your time-track.";
                alert(message);
                dataModified[i].focus();
                if(document.all)
                    event.returnValue = false;
                return false;
            }
            if(day >= 0 && day < 7) {
                if(total > 24 * 60) {
                    var message = "Time-track submitted for " + calLayout[day] + " exceeds 24 hours.\n" +
                                  "You cannot submit more than 24 hours per day.\n\n" +
                                  "Please decrease the time reported for " + calLayout[day] + " before submitting your time-track.";
                    alert(message);
                    dataModified[i].focus();
                    if(document.all)
                        event.returnValue = false;
                    return false;
                }
            }
            // check overtime
            var overtime = getOvertimeForDay(document.SubmitTTForm, day);
            if(overtime > total) {
                    var message = "Overtime submitted for " + calLayout[day] + " is greater than overall time reported for this day.\n" +
                                  "Overtime cannot be greater than day total.\n\n" +
                                  "Please correct the overtime value before submitting your time-track.";
                    alert(message);
                    if(document.SubmitTTForm.elements["overtime[" + day + "]"])
                        document.SubmitTTForm.elements["overtime[" + day + "]"].focus();
                    if(document.all)
                        event.returnValue = false;
                    return false;
            }
        }
        // overtime
        if(name.indexOf('overtime[') != -1) {
            var spent = parseSpent(dataModified[i].value);
            var day = name.substr(name.length - 2, 1);
            if(spent == null) {
                var message = "Overtime submitted for " + calLayout[day] + ' contains incorrect value: "' + dataModified[i].value + "\".\n" +
                              "Time should be entered in the format hh:mm. Number of minutes must be less than 60.\n\n" +
                              "Please correct the overtime value before submitting your time-track.";
                alert(message);
                dataModified[i].focus();
                if(document.all) {
                    event.returnValue = false;
                }
                return false;
            }
            if(day >=0 && day < 7) {
                var total = getDayTotal(document.SubmitTTForm, day);
                if(spent > total) {
                    var message = "Overtime submitted for " + calLayout[day] + " is greater than overall time reported for this day.\n" +
                                  "Overtime cannot be greater than day total.\n\n" +
                                  "Please correct the overtime value before submitting your time-track.";
                    alert(message);
                    dataModified[i].focus();
                    if(document.all)
                        event.returnValue = false;
                    return false;
                }
            }
        }
    }
    document.SubmitTTForm.pageAction.value = 'save_tt';
    document.SubmitTTForm.submit();
    return true;
}